/**
 * @class Spark.Component
 * @extends Ext.util.Observable
 * <p>所有组件对象的父类.
 * <p>所有的子类将自动继承Component的所有属性和方法.
 * @author njq.niu@hand-china.com
 * @constructor
 * @param {Object} config 配置对象. 
 */
$S.Component = Ext.extend(Ext.util.Observable,{
    constructor: function(config) {
        $S.Component.superclass.constructor.call(this);
        this.isHidden = false;
        this.isFireEvent = false;
        this.config=config;
        this.initComponent(config);
        this.initEvents();
        this.initBind();
        this.initStatus();
        if(config.register !== false) $S.CmpManager.put(this.id,this)
    },
    initConfig : function(config){
        config = config || {};
        this.id = config.id || Ext.id();
        Ext.apply(this, config);
    },
    initBind : function(){
        if(this.bt && this.name) this.bind(this.bt,this.name)
    },
    initComponent : function(config){
        this.initConfig(config);
        if(this.listeners){
            this.on(this.listeners);
        }
//        this.originalValue = this.getValue();
    },
    processListener: function(ou){},
    initStatus : function(){},
    initEvents : function(){
        this.addEvents(
        'change',
        /**
         * @event valid
         * 组件验证事件.
         * @param {Component} this 当前组件.
         * @param {Spark.Record} record record对象.
         * @param {String} name 对象绑定的Name.
         * @param {Boolean} isValid 验证是否通过.
         */
        'valid',
        /**
         * @event bind
         * bind事件.
         * @param {Component} this 当前组件.
         * @param {Spark.Record} record record对象.
         */
        'bind');
        this.processListener('on');
    },
    /**
     * 获取绑定的name
     * @return {String} 绑定的name
     */
    getBindName: function(){
        return this.binder ? this.binder.name : null;
    },
    /**
     * 获取绑定的DataSet
     * @return {Spark.DataSet} ds
     */
    getBindDataSet: function(){
        return this.binder ? this.binder.ds : null;
    },
    /**
     * 将组件绑定到某个DataSet的某个Field上.
     * @param {Spark.DataSet} dataSet 绑定的DataSet. 可以是具体某个DataSet对象，也可以是某个DataSet的id.
     * @param {String} name Field的name. 
     */
    bind : function(ds, name){
        this.clearBind();
        if(typeof(ds) == 'string'){
            ds = $(ds);
        }
        if(!ds)return;
        this.binder = {
            ds: ds,
            name:name
        }
        this.record = ds.current();
        var field =  ds.fields[this.binder.name];
        if(field) {
            var config={};
            Ext.apply(config,this.config);
            Ext.apply(config, field.pro);
            delete config.name;
            delete config.type;
            this.initComponent(config);  
            this.initStatus();
        }
        ds.on('metachange', this.onRefresh, this);
        ds.on('valid', this.onValid, this);
        ds.on('remove', this.onRemove, this);
        ds.on('clear', this.onClear, this);
        ds.on('update', this.onUpdate, this);
        ds.on('reject', this.onUpdate, this);
        ds.on('fieldchange', this.onFieldChange, this);
        ds.on('indexchange', this.onRefresh, this);
        this.onRefresh(ds)
        this.fireEvent('bind', this, this.record);
    },
    /**
     * 清除绑定.
     * <p>删除所有绑定的事件信息.
     */
    clearBind : function(){
        if(this.binder) {
            var bds = this.binder.ds;
            bds.un('metachange', this.onRefresh, this);
            bds.un('valid', this.onValid, this);
            bds.un('remove', this.onRemove, this);
            bds.un('clear', this.onClear, this);
            bds.un('update', this.onUpdate, this);
            bds.un('reject', this.onUpdate, this);
            bds.un('fieldchange', this.onFieldChange, this);
            bds.un('indexchange', this.onRefresh, this);
        } 
        this.binder = null; 
        this.record = null;
    },
    /**
     * 设置当前的值.
     * @param {Object} value 值对象
     * @param {Boolean} silent 是否更新到dataSet中
     */
    setValue : function(v, silent){
        var ov = this.value;
        this.value = v;
        if(silent === true)return;
        if(this.binder){
            this.record = this.binder.ds.current();
            if(this.record == null){
                this.record = this.binder.ds.create({},false);                
            }
            this.record.set(this.binder.name,v);
            if(Ext.isEmpty(v,true)) delete this.record.data[this.binder.name];
        }
        if(ov!=v){
            this.fireEvent('change', this, v, ov);
        }
    },
    /**
     * 返回当前值
     * @return {Object} value 返回值.
     */
    getValue : function(){
        var v = this.value;
        v = (v === null || v === undefined ? '' : v);
        return v;
    },
//    /**
//     * 重置  通过dataset来reset
//     */
//    reset : function(){
//        this.setValue(this.originalValue);
//    },
    /**
     * <p>销毁组件对象.</p>
     * <p>1.删除所有绑定的事件.</p>
     * <p>2.从对象管理器中删除注册信息.</p>
     * <p>3.删除dom节点.</p>
     */
    destroy : function(){
        this.processListener('un');
        $S.CmpManager.remove(this.id);
        this.clearBind();
    },
    render : function(record){
        this.record = record;
        if(this.record) {
            var value = this.record.get(this.binder.name);
            var field = this.record.getField(this.binder.name);     
            var config={};
            Ext.apply(config,this.config);
            Ext.apply(config, field.snap);
            this.initComponent(config);
            this.initStatus();
//          if(this.record.valid[this.binder.name]){
//              this.markInvalid();
//          }
            //TODO:和lov的设值有问题
//          if(this.value == value) return;
            if(!Ext.isEmpty(value,true)) {
                this.setValue(value,true);
            }else{
                this.clearValue();
            }
        } else {
            this.setValue('',true);
        }
    },
    onRemove : function(ds, record){
        if(this.binder.ds == ds && this.record == record){
            this.clearValue();
        }
    },
    onRefresh : function(ds){
        if(this.isFireEvent == true || this.isHidden == true) return;
        this.clearInvalid();
        this.render(ds.current());
    },
    onValid : function(ds, record, name, valid){
        if(this.binder.ds == ds && this.binder.name == name && this.record == record){
            if(valid){
                this.fireEvent('valid', this, this.record, this.binder.name, true)
                this.clearInvalid();
            }else{
                this.fireEvent('valid', this, this.record, this.binder.name, false);
                this.markInvalid();
            }
        }       
    },
    onUpdate : function(ds, record, name, value){
        if(this.binder.ds == ds && this.record == record && this.binder.name == name && this.getValue() !== value){
            this.setValue(value, true);
        }
    },
    onFieldChange : function(ds, record, field){
        if(this.binder.ds == ds && this.record == record && this.binder.name == field.name){
            this.onRefresh(ds);     
        }
    },
    onClear : function(ds){
        this.clearValue();    
    },
    clearInvalid : function(){},
    markInvalid : function(){},
    clearValue : function(){},
    initMeta : function(){},
    setDefault : function(){},
    setRequired : function(){},
    onDataChange : function(){}
});